Dynomotion

Group: DynoMotion Message: 10700 From: tmday7 Date: 12/22/2014
Subject: Encoder DRO Zero
Hi Tom,
Iam still customizing KmotionCNC. But am working on getting it fully functional right now.
In Mach3 i could zero the Encoders when i was in "manual mode".  With a "Notify Plugins" in a VB script button with....
 "NotifyPlugins(10100)
Sleep 300     
DoOEMButton (1008) "

Problem i have now (in KMcnc) is when iam in "Manual Mode"( which changes axes to OpenLoop) is when i click the zero button for an axis, the Encoder DRO does not fully zero. Sometimes there is .030 to .040 left in the DRO.

Do i need to make a user button execute a C Program or can the original Zero button ,for a given axis, be altered?

Thanks,
Troy
Group: DynoMotion Message: 10701 From: tmday7 Date: 12/22/2014
Subject: Re: Encoder DRO Zero
Here is my INIT c iam using in KmotionCNC. Its same as the one i use in Mach3 just a new name.

#include "KMotionDef.h"

#define FEEDHOLDBIT 21
#define MANUALBIT 25

#define X 0
#define Y 1
#define Z 2
#define A 3
 
void ServiceEStop(void);

int flast=0,flastsolid=-1,fcount=0;
int mlast=0,mlastsolid=-1,mcount=0;

int Manual,FeedHold;
   
int Debounce(int n, int *cnt, int *last, int *lastsolid);

main()
{
    #define DROIN 40
    double *pin  = (double *)&persist.UserData[(DROIN -1)*2];
   
    int result;

    Manual = !ReadBit(MANUALBIT);

    ch0->InputMode=ENCODER_MODE;
    ch0->OutputMode=CL_STEP_DIR_MODE;
    ch0->Vel=25000;
    ch0->Accel=180000;
    ch0->Jerk=18000000;
    ch0->P=0;
    ch0->I=0.005;
    ch0->D=0;
    ch0->FFAccel=0;
    ch0->FFVel=0;
    ch0->MaxI=200;
    ch0->MaxErr=1000000;
    ch0->MaxOutput=200;
    ch0->DeadBandGain=0;
    ch0->DeadBandRange=7;
    ch0->InputChan0=0;
    ch0->InputChan1=0;
    ch0->OutputChan0=8;
    ch0->OutputChan1=0;
    ch0->MasterAxis=-1;
    ch0->LimitSwitchOptions=0x1010000f;
    ch0->InputGain0=2.952759981155;
    ch0->InputGain1=1;
    ch0->InputOffset0=0;
    ch0->InputOffset1=0;
    ch0->OutputGain=1;
    ch0->OutputOffset=0;
    ch0->SlaveGain=1;
    ch0->BacklashMode=BACKLASH_OFF;
    ch0->BacklashAmount=0;
    ch0->BacklashRate=0;
    ch0->invDistPerCycle=1;
    ch0->Lead=0;
    ch0->MaxFollowingError=200;
    ch0->StepperAmplitude=20;

    ch0->iir[0].B0=1;
    ch0->iir[0].B1=0;
    ch0->iir[0].B2=0;
    ch0->iir[0].A1=0;
    ch0->iir[0].A2=0;

    ch0->iir[1].B0=1;
    ch0->iir[1].B1=0;
    ch0->iir[1].B2=0;
    ch0->iir[1].A1=0;
    ch0->iir[1].A2=0;

    ch0->iir[2].B0=0.0007688089972362;
    ch0->iir[2].B1=0.001537619973533;
    ch0->iir[2].B2=0.0007688089972362;
    ch0->iir[2].A1=1.920809984207;
    ch0->iir[2].A2=-0.9238849878311;

    ch1->InputMode=ENCODER_MODE;
    ch1->OutputMode=CL_STEP_DIR_MODE;
    ch1->Vel=25000;
    ch1->Accel=180000;
    ch1->Jerk=18000000;
    ch1->P=0;
    ch1->I=0.008;
    ch1->D=0;
    ch1->FFAccel=0;
    ch1->FFVel=0;
    ch1->MaxI=200;
    ch1->MaxErr=1000000;
    ch1->MaxOutput=200;
    ch1->DeadBandGain=0;
    ch1->DeadBandRange=7;
    ch1->InputChan0=1;
    ch1->InputChan1=0;
    ch1->OutputChan0=9;
    ch1->OutputChan1=0;
    ch1->MasterAxis=-1;
    ch1->LimitSwitchOptions=0x1111000f;
    ch1->InputGain0=-2.952759981155;
    ch1->InputGain1=1;
    ch1->InputOffset0=0;
    ch1->InputOffset1=0;
    ch1->OutputGain=1;
    ch1->OutputOffset=0;
    ch1->SlaveGain=1;
    ch1->BacklashMode=BACKLASH_OFF;
    ch1->BacklashAmount=0;
    ch1->BacklashRate=0;
    ch1->invDistPerCycle=1;
    ch1->Lead=0;
    ch1->MaxFollowingError=200;
    ch1->StepperAmplitude=20;

    ch1->iir[0].B0=1;
    ch1->iir[0].B1=0;
    ch1->iir[0].B2=0;
    ch1->iir[0].A1=0;
    ch1->iir[0].A2=0;

    ch1->iir[1].B0=1;
    ch1->iir[1].B1=0;
    ch1->iir[1].B2=0;
    ch1->iir[1].A1=0;
    ch1->iir[1].A2=0;

    ch1->iir[2].B0=0.0007688089972362;
    ch1->iir[2].B1=0.001537619973533;
    ch1->iir[2].B2=0.0007688089972362;
    ch1->iir[2].A1=1.920809984207;
    ch1->iir[2].A2=-0.9238849878311;


    ch2->InputMode=ENCODER_MODE;
    ch2->OutputMode=CL_STEP_DIR_MODE;
    ch2->Vel=25000;
    ch2->Accel=180000;
    ch2->Jerk=18000000;
    ch2->P=0;
    ch2->I=0.007;
    ch2->D=0;
    ch2->FFAccel=0;
    ch2->FFVel=0;
    ch2->MaxI=200;
    ch2->MaxErr=1000000;
    ch2->MaxOutput=200;
    ch2->DeadBandGain=0;
    ch2->DeadBandRange=5;
    ch2->InputChan0=2;
    ch2->InputChan1=0;
    ch2->OutputChan0=10;
    ch2->OutputChan1=0;
    ch2->MasterAxis=-1;
    ch2->LimitSwitchOptions=0x1212000f;
    ch2->InputGain0=2.952759981155;
    ch2->InputGain1=1;
    ch2->InputOffset0=0;
    ch2->InputOffset1=0;
    ch2->OutputGain=-1;
    ch2->OutputOffset=0;
    ch2->SlaveGain=1;
    ch2->BacklashMode=BACKLASH_OFF;
    ch2->BacklashAmount=0;
    ch2->BacklashRate=0;
    ch2->invDistPerCycle=1;
    ch2->Lead=0;
    ch2->MaxFollowingError=200;
    ch2->StepperAmplitude=20;

    ch2->iir[0].B0=1;
    ch2->iir[0].B1=0;
    ch2->iir[0].B2=0;
    ch2->iir[0].A1=0;
    ch2->iir[0].A2=0;

    ch2->iir[1].B0=1;
    ch2->iir[1].B1=0;
    ch2->iir[1].B2=0;
    ch2->iir[1].A1=0;
    ch2->iir[1].A2=0;

    ch2->iir[2].B0=0.0007689999765716;
    ch2->iir[2].B1=0.001537999953143;
    ch2->iir[2].B2=0.0007689999765716;
    ch2->iir[2].A1=1.920809984207;
    ch2->iir[2].A2=-0.9238849878311;
   
        ch3->InputMode=NO_INPUT_MODE;
    ch3->OutputMode=STEP_DIR_MODE;
    ch3->Vel=2500000;
    ch3->Accel=1000000;
    ch3->Jerk=9000;
    ch3->P=0;
    ch3->I=0.005;
    ch3->D=0;
    ch3->FFAccel=0;
    ch3->FFVel=0;
    ch3->MaxI=200;
    ch3->MaxErr=1e+006;
    ch3->MaxOutput=200;
    ch3->DeadBandGain=1;
    ch3->DeadBandRange=0;
    ch3->InputChan0=3;
    ch3->InputChan1=0;
    ch3->OutputChan0=11;
    ch3->OutputChan1=0;
    ch3->MasterAxis=-1;
    ch3->LimitSwitchOptions=0x0;
    ch3->InputGain0=1;
    ch3->InputGain1=1;
    ch3->InputOffset0=0;
    ch3->InputOffset1=0;
    ch3->OutputGain=1;
    ch3->OutputOffset=0;
    ch3->SlaveGain=1;
    ch3->BacklashMode=BACKLASH_OFF;
    ch3->BacklashAmount=0;
    ch3->BacklashRate=0;
    ch3->invDistPerCycle=1;
    ch3->Lead=0;
    ch3->MaxFollowingError=1000000000;
    ch3->StepperAmplitude=20;

    ch3->iir[0].B0=1;
    ch3->iir[0].B1=0;
    ch3->iir[0].B2=0;
    ch3->iir[0].A1=0;
    ch3->iir[0].A2=0;

    ch3->iir[1].B0=1;
    ch3->iir[1].B1=0;
    ch3->iir[1].B2=0;
    ch3->iir[1].A1=0;
    ch3->iir[1].A2=0;

    ch3->iir[2].B0=0.000769;
    ch3->iir[2].B1=0.001538;
    ch3->iir[2].B2=0.000769;
    ch3->iir[2].A1=1.92081;
    ch3->iir[2].A2=-0.923885;



    // check if the User wants Manual Mode
    if (Manual)
    {
        chan[X].OutputMode = STEP_DIR_MODE;
        chan[Y].OutputMode = STEP_DIR_MODE;
    }
    else
    {
        chan[X].OutputMode = CL_STEP_DIR_MODE;
        chan[Y].OutputMode = CL_STEP_DIR_MODE;
    }

    // enable/disable limits based on a
    // DRO downloaded from Mach3
   
   
    if (*pin == 0)
    {
        ch0->LimitSwitchOptions = 0x1010000f;
        ch1->LimitSwitchOptions = 0x1111000f;
        ch2->LimitSwitchOptions = 0x1212000f;
    }
    else
    {
        ch0->LimitSwitchOptions = 0x0;
        ch1->LimitSwitchOptions = 0x0;
        ch2->LimitSwitchOptions = 0x0;
    }

    EnableAxisDest(0,ch0->Position);
    EnableAxisDest(1,ch1->Position);
    EnableAxisDest(2,ch2->Position);
    EnableAxisDest(3,ch3->Dest);

    DefineCoordSystem(0,1,2,3);


    for (;;)
    {
        Manual = !ReadBit(MANUALBIT);
       
        // handle switching into or out of Manual Mode
        result = Debounce(Manual,&mcount,&mlast,&mlastsolid);
       
        if (result == 1)
        {
            // just entered manual mode
           
            DisableAxis(X);
            DisableAxis(Y);
            DisableAxis(Z);
            chan[X].OutputMode = STEP_DIR_MODE;
            chan[Y].OutputMode = STEP_DIR_MODE;
            chan[Z].OutputMode = STEP_DIR_MODE;
            EnableAxisDest(X,chan[X].Position);
            EnableAxisDest(Y,chan[Y].Position);
            EnableAxisDest(Z,chan[Z].Position);

            printf("Simulated Manual Mode on\n");
        }
       
        if (result == 0)
        {
            // just entered auto mode
           
            DisableAxis(X);
            DisableAxis(Y);
            DisableAxis(Z);
            chan[X].OutputMode = CL_STEP_DIR_MODE;
            chan[Y].OutputMode = CL_STEP_DIR_MODE;
            chan[Z].OutputMode = CL_STEP_DIR_MODE;

            EnableAxisDest(X,chan[X].Position);
            EnableAxisDest(Y,chan[Y].Position);
            EnableAxisDest(Z,chan[Z].Position);
            printf("Simulated Manual Mode off\n");
           
            printf("Pulse Estop\n");
           
            Delay_sec(1);
        }


        // handle Feedhold
        FeedHold = ReadBit(FEEDHOLDBIT);
       
        result = Debounce(FeedHold,&fcount,&flast,&flastsolid);
       
        if (result == 1)
        {
            // just entered Feed Hold mode
            StopCoordinatedMotion();  //feedhold
        }

        WaitNextTimeSlice();
    }

    return 0;
}



// Debounce a bit
//
// return 1 one time when first debounced high
// return 0 one time when first debounced low
// return -1 otherwise
#define DBTIME 300

int Debounce(int n, int *cnt, int *last, int *lastsolid)
{
    int v = -1;
   
    if (n == *last)  // same as last time?
    {
        if (*cnt == DBTIME-1)
        {
            if (n != *lastsolid)
            {
                v = *lastsolid = n;  // return debounced value
            }
        }
        if (*cnt < DBTIME)    (*cnt)++;
    }
    else
    {
        *cnt = 0;  // reset count
    }
    *last = n;
    return v;
}


Troy
Group: DynoMotion Message: 10702 From: Tom Kerekes Date: 12/22/2014
Subject: Re: Encoder DRO Zero
Hi Troy,

I believe we did the following to adjust the commanded Destination to match the Encoder Reading by disabling the Axis, and then re-enabling the axis at the destination of the current Encoder Position.

        // adjust the commanded position to match the glass scale encoder
        DisableAxis(X);
        EnableAxisDest(X,chan[X].Position);

Certainly you could create a User button to do this or modify what the Current Zero Button does to do this.

There are probably a number of different approaches.  Probably the simplest would be to first create a User Button to perform the operation above.  Then push the User Button followed by the Zero Button to see that it works correctly.

If so then modify the source code for:

OnSetX()

So that it automatically "pushes" the user button.  This can be accomplished by "Invoking the MCode Action" with:

            Interpreter->InvokeAction(11+xxx,FALSE);

where xxx is the User Button (less one)

You might then hide the User Button by changing the label to be blank.

HTH
Regards
TK

Group: DynoMotion Message: 10705 From: tmday7 Date: 12/22/2014
Subject: Re: Encoder DRO Zero
Hi Tom,
 Made a user button to update the command DRO. Clicking the new user button and then the zero button ,zeros out both command and encoder DRO.

Can the following code or something similar be added to the User button C code to also have the zero button action?

// adjust the commanded position to match the glass scale encoder
        DisableAxis(X);
        EnableAxisDest(X,chan[X].Position);


ON_BN_CLICKED(IDC_ZeroX, OnZeroX)

Thanks,
Troy
Group: DynoMotion Message: 10707 From: Tom Kerekes Date: 12/22/2014
Subject: Re: Encoder DRO Zero
Hi Troy,

Not quite.  You are mixing Windows MFC C++ Programming for the PC with KFLOP C Programming. 

But there is a mechanism for KFLOP to request KMotionCNC to do things like that.  There is a Set X request.  Zero is just a special case of "setting" the DRO to zero.

See this KFLOP Function:

DoPCFloat(PC_COMM_SET_X,0.0);

This is an example of how it can be used (you must include the KflopToKMotionCNCFunctions.c)

KFLOPtoPCCmdExamples.c

HTH
Regards
TK


Group: DynoMotion Message: 10714 From: tmday7 Date: 12/23/2014
Subject: Re: Encoder DRO Zero
Hi Tom,
I got some progress :)
I have 2 C programs that work independently, but cant figure out how to merge the 2 into 1.
Also, am i  thinking correctly that there would need to be a pause or wait of some sort between the 2 actions once they are merged into 1 C program?

Thanks again,
Troy
  @@attachment@@
Group: DynoMotion Message: 10717 From: tmday7 Date: 12/23/2014
Subject: Re: Encoder DRO Zero
Hay Tom,
 Believe i got it. :D
Attached C program works, but can you check it to make sure iam not missing something else?

Thanks,
Troy
  @@attachment@@
Group: DynoMotion Message: 10725 From: Tom Kerekes Date: 12/23/2014
Subject: Re: Encoder DRO Zero [1 Attachment]
Hi Troy,

Looks reasonable.  Except for the formatting and indentation which hurts my eyes :)

See attached (has the exact same functionality)

Regards
TK

Group: DynoMotion Message: 10726 From: tmday7 Date: 12/23/2014
Subject: Re: Encoder DRO Zero [1 Attachment]
Hi Tom,
Great. I'll work on that. :)
Thanks again,
Troy